#include "SDLRenderer.hpp"

#include "OpenGL.hpp"

#include <iostream>
using std::cout;
using std::endl;

SDLRenderer::SDLRenderer(IRendererHandler* handler,
						 const String title,
						 size_t width, size_t height,
						 size_t bpp, bool fullscreen)
	: m_handler(handler), m_width(width), m_height(height)
{
    m_aspect = (float)m_width / (float)m_height;
    
	//Initialise SDL
	if( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
		throw RendererException("Couldn't initialise SDL: "+String(SDL_GetError()));
	}
		
	//Set video mode
	size_t video_flags = SDL_OPENGL | SDL_HWSURFACE |
		SDL_DOUBLEBUF;// | SDL_NOFRAME;
	if( fullscreen ) video_flags |= SDL_FULLSCREEN | SDL_NOFRAME;
	SDL_Surface* screen = SDL_SetVideoMode(width, height, bpp, video_flags);
	if( 0 == screen ) {
		throw RendererException("Couldn't set "+toString(width)+"x"+
								toString(height)+"x"+toString(bpp)+
								" (fullscreen="+toString(fullscreen)+")"
								" video mode: "+String(SDL_GetError()));
	}

	cout << "Screen dimensions: " << screen->w << ", " << screen->h << endl;

	//Set window caption
	SDL_WM_SetCaption(title.c_str(), NULL);
	
	this->initOpenGL();
}

void SDLRenderer::initOpenGL()
{
	//glClear(GL_COLOR_BUFFER_BIT);
	//glViewport(0, 0, m_width, m_height);
	int viewport[4];
	glGetIntegerv(GL_VIEWPORT,viewport);
	cout << "Viewport: " << viewport[0] << ", " <<
		viewport[1] << ", " << viewport[2] << ", " << viewport[3] << endl;
	
	glViewport(0, 0, m_width/*/2*/, m_height/*/2*/);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(-m_aspect, m_aspect, -1.0, 1.0, 0.0, 1.0);
	glMatrixMode(GL_MODELVIEW);

	//Initialise our default OpenGL settings
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glClearDepth(1.0);
	//glDepthFunc(GL_LESS);
	//glEnable(GL_DEPTH_TEST);
	glShadeModel(GL_SMOOTH);
	
	glEnable(GL_BLEND);									//Enable alpha blending
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);	//Configure alpha blending

	//For textures
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glEnable(GL_TEXTURE_2D);
    
    // TODO: In theory this enables/disables vsync,
	//       but it's deprecated (why!?). The constant isn't defined.
    //SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 0);
}

void SDLRenderer::update()
{
	/*
	for( ViewportIter it=m_viewports.begin(); it!=m_viewports.end(); ++it ) {
		glViewport(it->getPos().x*m_width, it->getPos().y*m_height,
				   it->getSize().x*m_width, it->getSize().y*m_height);
		glLoadIdentity();
		
		render();
	}
	*/
	/*
	// TODO: This is a hack for testing out multiple viewport rendering
	for( int y=0; y<2; ++y ) {
		for( int x=0; x<2; ++x ) {
			glViewport(x*m_width/2, y*m_height/2, m_width/2, m_height/2);
			glLoadIdentity();
			//glClear(GL_DEPTH_BUFFER_BIT);
			
			glRotatef(45, x, y, 0);
			// Raise the frame event
			m_handler->onFrame(this);
		}
	}
	*/
	
	m_handler->onFrame(this);
	
	int gl_error = glGetError();
	if( gl_error != GL_NO_ERROR ) {
		cout << "OpenGL error " << gl_error << ": " << gluErrorString(gl_error) << endl;
	}
	
	// Render to screen
	SDL_GL_SwapBuffers();
	glClear(GL_COLOR_BUFFER_BIT);
	//glLoadIdentity();
};
